//
//  YangDate.swift
//  YangFoundation
//
//  Created by yuyang on 2021/12/21.
//

import Foundation

public class YangDate {
    /// YangDate支持的时间字符串类型
    enum YangDateFormat {
        case YearMonth              // 年月               示例: 2020-3
        case Month                  // 月份               示例: 2月
        case MonthNumber            // 月份               示例: 02
        case Week                   // 星期               示例: 星期四
        case Day                    // 日期               示例: 02
        case DetailTime             // 详细时间            示例: 2019-12-03 00:00:00
        case ToNow                  // 相对于当前时间的显示  示例: 2019-12-03 00:00; 03-20; 17:22; 前天 10:42; 昨天 10:42; 2小时前; 2分钟前; 刚刚
    }

    /// 获取时间字符串
    ///
    /// - Parameters:
    ///     - date: Date对象 默认当前Date()
    ///     - dateFormat: 需要转换的YangDateFormat类型
    /// - returns: 日期字符串
    static func timeString(date: Date = Date(), _ dateFormat: YangDateFormat) -> String {
        switch dateFormat {
        case .YearMonth:
            return YangDate.yearMonthString(date)
        case .Month:
            return YangDate.monthString(date)
        case .MonthNumber:
            return YangDate.monthNumberString(date)
        case .Week:
            return YangDate.weekString(date)
        case .Day:
            return YangDate.dayString(date)
        case .DetailTime:
            return YangDate.detailTimeString(date)
        case .ToNow:
            return YangDate.toNowTimeString(date)
        }
    }

    /// 获取时间字符串
    ///
    /// - Parameters:
    ///     - timeStamp: 毫秒时间戳(TimeInterval)
    ///     - dateFormat: 需要转换的YangDateFormat类型
    /// - returns: 日期字符串
    static func timeString(timeStamp: TimeInterval?, _ dateFormat: YangDateFormat) -> String {
        let date = YangDate.date(timeStamp: timeStamp)
        return YangDate.timeString(date: date, dateFormat)
    }

    /// 获取时间字符串
    ///
    /// - Parameters:
    ///     - timeStamp: 毫秒时间戳(Int64)
    ///     - dateFormat: 需要转换的YangDateFormat类型
    /// - returns: 日期字符串
    static func timeString(timeStamp: Int64?, _ dateFormat: YangDateFormat) -> String {
        let date = YangDate.date(timeStamp: timeStamp)
        return YangDate.timeString(date: date, dateFormat)
    }

    /// 毫秒时间戳转Date
    ///
    /// - Parameters:
    ///     - timeStamp: 毫秒时间戳(TimeInterval)
    /// - returns: Date
    static func date(timeStamp: TimeInterval?) -> Date {
        let timeInterval = TimeInterval((timeStamp ?? 0) / 1000)
        return Date(timeIntervalSince1970: timeInterval)
    }

    /// 毫秒时间戳转Date
    ///
    /// - Parameters:
    ///     - timeStamp: 毫秒时间戳(Int64)
    /// - returns: Date
    static func date(timeStamp: Int64?) -> Date {
        let timeInterval = TimeInterval((timeStamp ?? 0) / 1000)
        return Date(timeIntervalSince1970: timeInterval)
    }

    /// Date转年月
    /// - returns:
    ///     返回示例 2020-3
    private static func yearMonthString(_ date: Date) -> String {
        let fmt = DateFormatter()
        fmt.locale = Locale.init(identifier: "en_US")
        fmt.dateFormat = "yyyy-M"
        return fmt.string(from: date)
    }

    /// Date转月份
    /// - returns:
    ///     返回示例 2月
    private static func monthString(_ date: Date) -> String {
        let fmt = DateFormatter()
        fmt.locale = Locale.init(identifier: "zh_CN")
        fmt.dateFormat = "MMM"
        return fmt.string(from: date)
    }

    /// Date转月份
    /// - returns:
    ///     返回示例 02
    private static func monthNumberString(_ date: Date) -> String {
        let fmt = DateFormatter()
        fmt.locale = Locale.init(identifier: "en_US")
        fmt.dateFormat = "MM"
        return fmt.string(from: date)
    }

    /// Date转星期
    /// - returns:
    ///     返回示例 星期四
    private static func weekString(_ date: Date) -> String {
        let fmt = DateFormatter()
        fmt.locale = Locale.init(identifier: "zh_CN")
        fmt.dateFormat = "EEEE"
        return fmt.string(from: date)
    }

    /// Date转日
    /// - returns:
    ///     返回示例 02
    private static func dayString(_ date: Date) -> String {
        let fmt = DateFormatter()
        fmt.dateFormat = "dd"
        return fmt.string(from: date)
    }

    /// Date转详细时间
    /// - returns:
    ///     返回示例 2019-12-03 00:00:00
    private static func detailTimeString(_ date: Date) -> String {
        let fmt = DateFormatter()
        fmt.dateFormat = "yyyy-MM-dd HH:mm:ss"
        return fmt.string(from: date)
    }

    /// 相对于当前时间的显示
    /// - returns:
    ///     返回示例 2019-12-03 00:00; 03-20; 17:22; 前天 10:42; 昨天 10:42; 2小时前; 2分钟前; 刚刚
    private static func toNowTimeString(_ date: Date) -> String {
        let currentDate = Date()

        // 年份差
        let currentYear = Calendar.autoupdatingCurrent.dateComponents([.year], from: currentDate)
        let pastYear = Calendar.autoupdatingCurrent.dateComponents([.year], from: date)
        let realComponents = Calendar.autoupdatingCurrent.dateComponents([.year, .day, .hour, .minute], from: date, to: currentDate)

        // startOfDay时间差
        let dateStartOfToday = Calendar.autoupdatingCurrent.startOfDay(for: currentDate)
        let dateStartOfPast = Calendar.autoupdatingCurrent.startOfDay(for: date)
        let dayComponents = Calendar.autoupdatingCurrent.dateComponents([.day], from: dateStartOfPast, to: dateStartOfToday)

        let fmt = DateFormatter()

        if (currentYear.year ?? 0) - (pastYear.year ?? 0) >= 1 { // 超过一年
            fmt.dateFormat = "yyyy-MM-dd HH:mm"
            return fmt.string(from: date)
        } else if (dayComponents.day ?? 0) >= 3 { // 超过3天
            fmt.dateFormat = "MM-dd HH:mm"
            return fmt.string(from: date)
        } else if (dayComponents.day ?? 0) == 2 { // 前天
            fmt.dateFormat = "HH:mm"
            let timeString = "前天 \(fmt.string(from: date))"
            return timeString
        } else if realComponents.day == 1 { // 超过24小时的昨天
            fmt.dateFormat = "HH:mm"
            let timeString = "昨天 \(fmt.string(from: date))"
            return timeString
        } else if let hoursDiff = realComponents.hour, hoursDiff < 24 && hoursDiff >= 1 { // 24小时内
            return "\(hoursDiff)小时前"
        } else if let minutesDiff = realComponents.minute, minutesDiff >= 1 { // 1小时内
            return "\(minutesDiff)分钟前"
        } else { // 1分钟内
            return "刚刚"
        }
    }
}
